<?php


namespace App\Services;

use App\Models\Admin;
use App\Models\ChatGroup;
use App\Models\ChatGroupMessages;
use App\Models\ChatRooms;
use App\Models\ChatMessage;
use App\Models\ChatUser;
use App\Models\User;
use FreeAbrams\FuncTools\AccessToken\Token;
use GatewayWorker\Lib\Gateway;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

/**
 * Created By FreeAbrams
 * Date: 2021/9/24
 */
class ChatService
{
	private $model;
	
	public function __construct($token)
	{
		$this->model = self::validateData($token);
	}
	
	static public function validateData(string $data)
    {
    	$key = config('api');
        $token = new Token($key['publicKey'], $key['signKey']);
        $datas = json_decode($token->decrypt($data), true);
        
        if (!$datas) {
        	throw new \Exception('validate failed.');
        }
        
        $chatUser = ChatUser::query()->find($datas['id']);
        
		if (!$chatUser) {
			throw new \Exception('user does not exist.');
		}
		
        return $chatUser;
    }
    
    /**
	 * 绑定设备
	 * @param $client_id
	 * @param $message
	 * @throws \Exception
	 */
    public function bind($client_id, $message)
	{
		$_SESSION['member_id'] = $this->model->id;
		
		$client_ids = Gateway::getClientIdByUid($this->model->id);
		if (!in_array($client_id, $client_ids)) {
			Gateway::bindUid($client_id, $this->model->id);
		}
		
		return ['type' => 'login', 'client_id' => $client_id, 'data' => $this->model, 'code' => 200];
	}
	
	/**
	 * 解除设备绑定
	 * @param $client_id
	 * @param $message
	 * @return bool
	 * @throws \Exception
	 */
	static public function unbind($client_id, $message)
	{
		$user_id = Gateway::getUidByClientId($client_id);
		if (!$user_id) {
			throw new \Exception('不存在此用户');
		}
		return self::showMsg(['type' => 'unbind']);
	}
	
	public function group_list($client_id, $message)
	{
		$validate = Validator::make($message, [
			'data.limit' => 'required|numeric',
			'data.page' => 'required|numeric'
		]);
		if ($validate->fails()) {
			throw new \Exception($validate->errors()->first());
		}
		$data = $message['data'];
		$offset = ($data['page'] - 1) * $data['limit'];
		$auth_id = Gateway::getUidByClientId($client_id);
		if ($auth_id != $this->model->id) {
			throw new \Exception('auth failed');
		}
		$where = [];
    	$where[] = ['inviter_id', '=', $auth_id];
    	$where[] = ['invitee_id', '=', $auth_id, "or"];
    	$group = ChatGroup::query()->where($where)->with(['inviter:id,related_table_type,related_table_id', 'invitee:id,related_table_type,related_table_id'])
		    ->limit($data['limit'])
		    ->offset($offset)
		    ->get(['id', 'inviter_id', 'invitee_id', 'created_at']);
    	
    	$message = ChatGroupMessages::query()->whereIn('chat_group_id', $group->pluck('id'))
		    ->where('is_last', 1)
		    ->limit($group->count())
		    ->get(['chat_group_id', 'chat_user_id', 'content', 'type']);
    	
    	return ['type' => 'group_list', 'data' => ['list' => $group, 'message' => $message], 'code' => 200];
	}
	
	public function group_send_msg($client_id, $message)
    {
		$validate = Validator::make($message, [
			'data.chat_group_id' => 'required|numeric',
			'data.type' => 'required|numeric',
            'data.content' => 'required',
		]);
		if ($validate->fails()) {
			throw new \Exception($validate->errors()->first());
		}
		$message = $message['data'];
        $group = ChatGroup::query()->find($message['chat_group_id']);
		if (!$group) {
			throw new \Exception('data does not fund');
		}
        $uid = Gateway::getUidByClientId($client_id);
        $data = [
            'chat_group_id' => $group->id,
	        'chat_user_id' => $uid,
            'type' => $message['type'],
            'content' => htmlspecialchars($message['content']),
            'read_num' => 0,
            'is_push' => 2,
            'remarks' => '',
	        'is_last' => 1,
        ];
        DB::beginTransaction();
	    try {
	    	$where = [];$return = []; $user_data = [];
	    	$where[] = ['chat_group_id', '=', $group->id];
	    	$where[] = ['is_last', '<', 2];
	    	ChatGroupMessages::query()->where($where)->update(['is_last' => 2]);
			$group_message = ChatGroupMessages::query()->create($data);
			if (!$group_message) {
				throw new \Exception('table message update nothing');
			}
			DB::commit();
			$where = [];
			$where = $group->only(['inviter_id', 'invitee_id']);
			$return[] = Arr::only($group_message->toArray(), ['id', 'chat_group_id', 'chat_user_id', 'type', 'content', 'read_num', 'created_at']);
            $user_data = $chatUser = ChatUser::with(['related_table:id,nickname,avatar'])->whereIn('id', $where)->get(['id', 'related_table_type', 'related_table_id']);
            self::sendMsg($group->only(['inviter_id', 'invitee_id']), ['type' => 'group_send_msg', 'data' => ['message' => $return, 'user_data' => $user_data]]);
	    } catch (\Exception $e) {
	        DB::rollBack();
	        self::sendMsg($group->only(['inviter_id', 'invitee_id']), ['type' => 'group_send_msg', 'data' => ['message' => $return, 'user_data' => $user_data, 'er' => $e->getMessage()]]);
	    }
	    return false;
    }
	
	static public function group_message_record($client_id, $message)
	{
		$validate = Validator::make($message, [
			'data.chat_group_id' => 'required|numeric',
			'data.limit' => 'required|numeric',
			'data.page' => 'required|numeric',
			'data.direction' => Rule::in(['desc', 'asc']),
		]);
		if ($validate->fails()) {
			throw new \Exception($validate->errors()->first());
		}
		$message = $message['data'];
		$offset = ($message['page'] - 1) * $message['limit'];
		$chat_group_id = $message['chat_group_id'];
		$data = ChatGroupMessages::query()->where('chat_group_id', $chat_group_id)
			->orderBy('created_at', $message['direction'])
			->offset($offset)
			->limit($message['limit'])
			->get(['id', 'chat_user_id', 'content', 'type', 'created_at'])->toArray();
		
		$chat_user_id = array_column($data, 'chat_user_id');
		$chat_user_id = array_flip($chat_user_id);
		$chat_user_id[Gateway::getUidByClientId($client_id)] = 1;
		$chat_user_id = array_keys($chat_user_id);
		
		$chatUser = ChatUser::with(['related_table'])->whereIn('id', $chat_user_id)->get(['id', 'related_table_type', 'related_table_id']);
		
		return ['type' => 'group_message_record', 'data' => ['message'=> $data, 'user_data' => $chatUser], 'code' => 200];
	}
	
	static public function group_bind($client_id, $message)
	{
		$data = self::validateData(isset($message['token'])?$message['token']:'');
		$chatUser = ChatUser::query()->find($data['id']);
		if (!$chatUser) {
			return ['code' => 400, 'msg' => 'user does not exist.'];
			//throw new \Exception('user does not exist.');
		}
		$message = $message['data'];
		$id = [$chatUser->id, $message['chat_user_id']];
		sort($id);
		$where = [
			'inviter_id' => $id[0],
			'invitee_id' => $id[1],
		];
		
		$group = ChatGroup::query()->firstOrCreate($where);
		
		return ['type' => 'group_bind', 'client_id' => $client_id, 'data' => $group, 'code' => 200];
	}
	
    static public function group_message_read($client_id, $message)
    {
		$validate = Validator::make($message, [
			'chat_group_id' => 'required|numeric',
		]);
		if ($validate->fails()) {
			return ['code' => 400];
		}
        $group = ChatGroup::query()->find($message['group_id']);
		if (!$group) {
			return ['code' => 400];
		}
		ChatGroupMessages::query()->where('chat_group_id', $message['group_id'])->update(['is_push', 1]);
		
		return ['type' => 'group_message_read', 'data' => [], 'code' => 200];
    }

    static public function sendMsg($uid= [],$data = [], $errno = '200', $errmsg = 'SUCCESS')
    {
        $return['errno'] = $errno;
        $return['errmsg'] = $errmsg;
        $return['data'] = $data;
        Gateway::sendToUid($uid,json_encode($return));
    }
	
	static public function showMsg($data = [], $errno = '200', $errmsg = 'SUCCESS')
    {
        $return['errno'] = $errno;
        $return['errmsg'] = $errmsg;
        $return['data'] = $data;
        return Gateway::sendToCurrentClient(json_encode($return));
    }
}